package ui

import (
	"image/color"
	"lnzw/server/test/test_fyne/test_3/data"
	"lnzw/server/test/test_fyne/test_3/data/unit"
	"sync"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/canvas"
)

// const offset = 5
const viewrange = 100

type PlayerUI struct {
	IUIBase
	Player     *unit.PlayerUnit
	Me         bool
	Circle     *canvas.Circle
	ViewCircle *canvas.Circle
	ViewRect   *canvas.Rectangle
	myview     sync.Map
}

func NewPlayerUI(player *unit.PlayerUnit, parentUI IUIBase) *PlayerUI {
	ui := &PlayerUI{
		Player:  player,
		IUIBase: parentUI,
	}
	return ui
}

func (p *PlayerUI) Init() {
	p.draw()
}

func (p *PlayerUI) GetUnit() data.IUnit { return p.Player }

func (p *PlayerUI) draw() {
	circle := canvas.NewCircle(color.RGBA{R: 0, G: 0, B: 255, A: 255})
	point := p.Player.GetPosition()
	circle.Position1 = fyne.NewPos(point.X+float32(offset_x)-data.Offset, point.Y-data.Offset+float32(offset_y))
	circle.Position2 = fyne.NewPos(point.X+float32(offset_x)+data.Offset, point.Y+data.Offset+float32(offset_y))
	p.Circle = circle
	p.GetContainer().Add(circle)
	if p.Me {
		//p.Player.NowMap
		vc := canvas.NewCircle(color.RGBA{R: 0, G: 0, B: 0, A: 100})
		point := p.Player.GetPosition()
		vc.Position1 = fyne.NewPos(point.X+float32(offset_x)-viewrange, point.Y-viewrange+float32(offset_y))
		vc.Position2 = fyne.NewPos(point.X+float32(offset_x)+viewrange, point.Y+viewrange+float32(offset_y))
		p.ViewCircle = vc
		p.GetContainer().Add(vc)

		p.ViewRect = canvas.NewRectangle(color.RGBA{R: 0, G: 0, B: 0, A: 100})
		p.ViewRect.Resize(fyne.NewSize(viewrange*2, viewrange*2))
		p.ViewRect.Move(fyne.NewPos(point.X+float32(offset_x)-viewrange, point.Y+float32(offset_y)-viewrange))
		p.GetContainer().Add(p.ViewRect)

		//监控键盘按键
		p.GetWindow().Canvas().SetOnTypedKey(func(e *fyne.KeyEvent) {
			point := p.Player.GetPosition()
			movx := 0
			movy := 0
			movstep := p.Player.NowMap.GetCellSize()
			switch e.Name {
			case fyne.KeyW:
				movy = -movstep
			case fyne.KeyS:
				movy = movstep
			case fyne.KeyA:
				movx = -movstep
			case fyne.KeyD:
				movx = movstep
			}
			p.Player.NowMap.MoveTo(p.Player, int(point.X+float32(movx)), int(point.Y+float32(movy)))
		})
	}
}

func (p *PlayerUI) Update() {
	point := p.Player.GetPosition()
	p.Circle.Position1 = fyne.NewPos(point.X+float32(offset_x)-data.Offset, point.Y-data.Offset+float32(offset_y))
	p.Circle.Position2 = fyne.NewPos(point.X+float32(offset_x)+data.Offset, point.Y+data.Offset+float32(offset_y))
	p.Circle.Refresh()
	if p.Me {
		p.ViewCircle.Position1 = fyne.NewPos(point.X+float32(offset_x)-viewrange, point.Y-viewrange+float32(offset_y))
		p.ViewCircle.Position2 = fyne.NewPos(point.X+float32(offset_x)+viewrange, point.Y+viewrange+float32(offset_y))
		p.ViewCircle.Refresh()

		p.ViewRect.Move(fyne.NewPos(point.X+float32(offset_x)-viewrange, point.Y+float32(offset_y)-viewrange))
		p.ViewRect.Refresh()
	}
}

func (p *PlayerUI) Destroy() {
	p.GetContainer().Remove(p.Circle)
}

func (p *PlayerUI) Tick() {
	p.Update()
	units := p.Player.NowMap.Watch(p.Player)
	mapunits := make(map[int64]data.IUnit, len(units))
	for i := 0; i < len(units); i++ {
		unit := units[i]
		mapunits[unit.GetUnitId()] = unit
	}
	p.myview.Range(func(id, unit interface{}) bool {
		if _, ok := mapunits[id.(int64)]; !ok {
			unit.(IUnitUI).Destroy()
			p.myview.Delete(id)
		}
		return true
	})
	for _, u := range units {
		if pui, ok := p.myview.Load(u.GetUnitId()); ok {
			pui.(IUnitUI).Update()
			continue
		}
		if u.GetUnitType() == data.Player {
			playerui := NewPlayerUI(u.(*unit.PlayerUnit), p.IUIBase)
			playerui.Init()
			p.myview.Store(u.GetUnitId(), playerui)
		}
		if u.GetUnitType() == data.Monster {
			monsterui := NewMonsterUI(u.(*unit.MonsterUnit), p.IUIBase)
			monsterui.Init()
			p.myview.Store(u.GetUnitId(), monsterui)
		}
	}
}
